#pragma once

#include "Format.h"
class CBytebuffer
{
public:
	CBytebuffer(char* p, unsigned int s)
	{
		pb = p;
		size = s;
		pImp = new CEasyFormat();
		ptr = 0;
		b_new = true;
	}
	CBytebuffer(char* p, unsigned int s, CFormat* pfmt)
	{
		pb = p;
		size = s;
		pImp = pfmt;
		ptr = 0;
		b_new = false;
	}
private:
	CBytebuffer(){};
public:
	virtual ~CBytebuffer(void)
	{
		if (pImp && b_new)
		{
			delete pImp;
		}
	}
public:
	char* pb;
	unsigned int ptr;
	unsigned int size;
	CFormat* pImp;
	bool b_new;

public:
	inline int get_rest_size()
	{
		return size-ptr;
	}
	void advance(int i)
	{
		ptr += i;
	}
	int payload()
	{
		return ptr;
	}
	char* str()
	{
		return pb;
	}
	bool parse_varint32(int& t)
	{
		int s = 0;
		int ret = pImp->parse_varint32(s, pb+ptr, get_rest_size());
		if (ret < 0)
		{
			return false;
		}
		advance(ret);
		t = s;
		return true;
	}
	bool parse_varint64(int64& t)
	{
		int64 s = 0;
		int ret = pImp->parse_varint64(s, pb+ptr, get_rest_size());
		if (ret < 0)
		{
			return false;
		}
		advance(ret);
		t = s;
		return true;
	}
	bool parse_string(string & t)
	{
		string s ;
		int ret = pImp->parse_string(s, pb+ptr, get_rest_size());
		if (ret < 0)
		{
			return false;
		}
		advance(ret);
		t = s;
		return true;
	}
	bool parse_fixedint32(int& t)
	{
		int s = 0;
		int ret = pImp->parse_fixedint32(s, pb+ptr, get_rest_size());
		if (ret < 0)
		{
			return false;
		}
		advance(ret);
		t = s;
		return true;
	}
	bool parse_fixedint64(int64& t)
	{
		int64 s = 0;
		int ret = pImp->parse_fixedint64(s, pb+ptr, get_rest_size());
		if (ret < 0)
		{
			return false;
		}
		advance(ret);
		t = s;
		return true;
	}
	int get_tag_datatype(int& dt)
	{
		int tag = 0;
		int ret = parse_varint32(tag);
		if (ret < 0)
		{
			return -1;
		}
		dt = tag & 0x07;
		return tag>>3;
	}
	unsigned int build_tag(unsigned int idx, unsigned int datatype)
	{
		return (idx<<3)+datatype;
	}
	bool write_fixedint32(int t)
	{
		int ret = pImp->write_fixedint32(t, pb+ptr, get_rest_size());
		if (ret < 0)
		{
			return false;
		}
		advance(ret);
		return true;
	}
	bool write_fixedint64(int64 t)
	{
		int ret = pImp->write_fixedint64(t, pb+ptr, get_rest_size());
		if (ret < 0)
		{
			return false;
		}
		advance(ret);
		return true;
	}
	bool write_string(string t)
	{
		int ret = pImp->write_string(t, pb+ptr, get_rest_size());
		if (ret < 0)
		{
			return false;
		}
		advance(ret);
		return true;
	}
	bool write_varint32(int t)
	{
		int ret = pImp->write_varint32(t, pb+ptr, get_rest_size());
		if (ret < 0)
		{
			return false;
		}
		advance(ret);
		return true;
	}
	bool write_varint64(int64 t)
	{
		int ret = pImp->write_varint64(t, pb+ptr, get_rest_size());
		if (ret < 0)
		{
			return false;
		}
		advance(ret);
		return true;
	}
	bool append(char* s, unsigned int len)
	{
		if (len<=get_rest_size())
		{
			memcpy(pb+ptr,s,len);
			advance(len);
			return true;
		}
		return false;
	}
	char * get_cur()
	{
		return pb+ptr;
	}
	bool parse_unknown_pass(DATA_TYPE dt)
	{
		int len = pImp->parse_unknown_pass(dt, pb+ptr, get_rest_size());
		if (len < 0)
		{
			return false;
		}
		if (len<=get_rest_size())
		{
			advance(len);
			return true;
		}
		return false;
	}

};
